/**
 * 获取数据类型
 * @date 2023-06-28
 * @param {any} obj:any 待检测的数据类型
 * @returns {string} 返回对应数据类型
 */
export function getObjType(obj: any): string {
  let toString = Object.prototype.toString;
  enum ObjTypes {
    '[object Boolean]' = 'boolean',
    '[object Number]' = 'number',
    '[object String]' = 'string',
    '[object Function]' = 'function',
    '[object Array]' = 'array',
    '[object Date]' = 'date',
    '[object RegExp]' = 'regExp',
    '[object Undefined]' = 'undefined',
    '[object Null]' = 'null',
    '[object Object]' = 'object'
  };
  if (obj instanceof Element) {
    return 'element';
  }
  
  return ObjTypes[toString.call(obj) as keyof typeof ObjTypes];
};


/**
 * 对象深拷贝
 */
export function deepClone<D>(data: D): D {
  let type = getObjType(data);
  let obj: D = undefined as D;
  if (type === 'array') {
    (obj as any[]) = [];
  } else if (type === 'object') {
    (obj as Object) = {};
  } else {
    //不再具有下一层次
    return data;
  }
  if (Array.isArray(data)) {
    for (let i = 0, len = data.length; i < len; i++) {
      (obj as any[]).push(deepClone(data[i]));
    }
  } else if (type === 'object') {
    for (let key in data) {
      obj[key] = deepClone((data as any)[key]);
    }
  }
  return obj;
};


/**
 * 检测数据是否为空
 * @date 2023-06-28
 * @param {any} val:any 检测的值
 * @returns {boolean} 返回是否为空
 */
export function validatenull(val: any) {
  if (typeof val == 'boolean') {
    return false;
  }
  if (typeof val == 'number') {
    return false;
  }
  if (val instanceof Array) {
    if (val.length == 0) return true;
  } else if (val instanceof Object) {
    if (JSON.stringify(val) === '{}') return true;
  } else {
    if (val == 'null' || val == null || val == 'undefined' || val == undefined || val == '') return true;
    return false;
  }
  return false;
}


/**
 * 函数防抖
 * @param func 
 * @param wait 等待执行时间
 */
export function debounce(func: Function, wait = 1000) {
  let timerId: number;

  return function _debounce(...args: any[]) {
    // @ts-ignore
    let context = this;

    if (timerId !== null) clearTimeout(timerId);

    timerId = setTimeout(function () {
      func.apply(context, args)
    }, wait);
  }
}


/**
 * 函数节流
 * @param func 
 * @param delay 延迟执行时间
 */
export function throttle(func: Function, delay = 1000) {
  let lastInvokeTime = 0;

  return function _throttle(...args: any[]) {
    // @ts-ignore
    let context = this;
    let now = Date.now();
    
    if (now - lastInvokeTime > delay) {
      func.apply(context, args);
      lastInvokeTime = Date.now();
    }
  }
}


/**
 * 动画函数
 * @param duration 动画持续时间
 * @param from 动画的起始位置
 * @param to 动画的结束位置
 * @param onProgress 动画进度回调
 */
export function animation(duration: number, from: number, to: number, onProgress: Function) {
  const speed = (to - from) / duration
  const startTime = Date.now();

  let value = from;
  function _run() {
    const now = Date.now()
    const time = now - startTime
    value = from + speed * time
    if (time >= duration) {
      value = to;
      onProgress && onProgress(value)
      return;
    }
    onProgress && onProgress(value)
    requestAnimationFrame(_run)
  }

  _run()
}


/**
 * 
 * @param time 等待时间
 */
export function sleep(time: number) {
  const now = Date.now()
  while (Date.now() - now < time) {}
}